/**
 * VYPe11 Project
 * VYPe11 language compiler.
 * Authors: Jozef Lang (xlangj01), 
 * 			Zoltan Zemko (xzemko01)
 * 2011
 */
package cz.vutbr.fit.VYPe.team18.VYPe11.sematic.declared;

import java.util.LinkedList;

import cz.vutbr.fit.VYPe.team18.VYPe11.exception.SematicException;
import cz.vutbr.fit.VYPe.team18.VYPe11.nodes.data_type.DataType;
import cz.vutbr.fit.VYPe.team18.VYPe11.nodes.data_type.DataTypeNode;
import cz.vutbr.fit.VYPe.team18.VYPe11.nodes.expression.ExpressionNode;
import cz.vutbr.fit.VYPe.team18.VYPe11.nodes.expression.terminal.FunctionInvocationNode;
import cz.vutbr.fit.VYPe.team18.VYPe11.nodes.function.FunctionDeclarationNode;
import cz.vutbr.fit.VYPe.team18.VYPe11.nodes.function.FunctionDefinitionNode;
import cz.vutbr.fit.VYPe.team18.VYPe11.nodes.function.ParameterNode;

public class Function extends DeclaredItem {
	private DataType returnType;
	private String id;
	private LinkedList<Variable> argumentList;
	private Boolean isDefined=false;
	
	public Function(DataType returnDataType,
							String id, 
							LinkedList<Variable> argument) 
	{
		this.returnType=returnDataType;
		this.id=id;
		this.argumentList=argument;
	}
	
	public Function(FunctionDeclarationNode node)
	{
		this.returnType=node.getReturnType().getType();
		this.id=node.getId().getId();
		argumentList=new LinkedList<Variable>();
		int i=0;
		for (DataTypeNode dtNode : node.getDataTypeList()) {
			argumentList.add(
					new Variable(dtNode.getType(),"v"+i)
			);
		}
	}
	
	public Function(FunctionDefinitionNode node) throws SematicException
	{
		this.returnType=node.getReturnType().getType();
		this.id=node.getId().getId();
		this.argumentList=new LinkedList<Variable>();
		this.isDefined=true;
		for (ParameterNode parNode : node.getParameterList()) {
			DataType argDT=parNode.getType().getType();
			String id=parNode.getId().getId();
			// Overi sa, ci rovnakym nazvom uz neexistuje parameter
			for(int i=0; i<argumentList.size(); i++)
			{
				if(id.equals(argumentList.get(i).getId()))
					throw new SematicException("More parameters in function "
							+this.id+"() has same name.");
			}
			
			// prida sa argument do zoznamu argumentov
			argumentList.add(new Variable(argDT, id));
		}
	}

	public Function(FunctionInvocationNode node) throws SematicException
	{
		this.id=node.getId().getId();
		argumentList=new LinkedList<Variable>();
		
		int i=0;
		for (ExpressionNode exprNode : node.getExpressionList()) {
			argumentList.add(
					new Variable(exprNode.getType(),"v"+i)
			);
		}
	}
	
	public DataType getReturnType() {
		return returnType;
	}

	public String getId() {
		return id;
	}

	public LinkedList<Variable> getArgumentList() {
		return argumentList;
	}

	public Boolean getIsDefined() {
		return isDefined;
	}

	public void setIsDefined(Boolean isDefined) {
		this.isDefined = isDefined;
	}
	
	public boolean isEqual(Function fun) {
		if(fun.getId()==this.id
			&& fun.getReturnType()==this.returnType
			&& fun.getArgumentList().size()==this.argumentList.size())
		{
			for(int i=0; i<this.argumentList.size(); i++)
			{
				if(this.argumentList.get(i)!=fun.getArgumentList().get(i))
					return false;
			}
			return true;				
		}
		else
		{
			return false;
		}
	}
}
